//package com.allwees.bs.c.common.auth.config;
//
//import com.allwees.bs.c.common.auth.oauth.OAuth2ResourceConfig;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.context.annotation.Lazy;
//import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
//import org.springframework.security.config.annotation.web.builders.HttpSecurity;
//import org.springframework.security.core.Authentication;
//import org.springframework.security.oauth2.provider.authentication.BearerTokenExtractor;
//import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter;
//import org.springframework.security.oauth2.provider.authentication.TokenExtractor;
//import org.springframework.security.web.DefaultSecurityFilterChain;
//import org.springframework.security.web.util.matcher.RequestMatcher;
//import org.springframework.web.filter.OncePerRequestFilter;
//
//import javax.servlet.Filter;
//import javax.servlet.FilterChain;
//import javax.servlet.ServletException;
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletRequestWrapper;
//import javax.servlet.http.HttpServletResponse;
//import java.io.IOException;
//import java.util.Collections;
//import java.util.Enumeration;
//import java.util.HashSet;
//import java.util.Set;
//
///**
// * 对于匹配到permitAll的URL，如果request携带了Authorization，则在OAuth2AuthenticationProcessingFilter检测token有效性前，去除Authorization（否则
// * 有可能会因为token失效而报InvalidTokenException）
// * 2019-11-09补记：此功能上线后，发现某些permitAll的url报InvalidTokenException，原因是这些url在已登录的情况下最终还是要验证token的，直接去除
// * Authorization会报以上异常。所以调整实现代码，提前验证Token有效性，如果无效，则去除Authorization；如果有效，则保持不变。
// *
// * @author yangylsky
// * @since 2019-11-07
// *
// */
//@Configuration
//@Lazy(false)
////@Slf4j
//public class PermitAllSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
//	private TokenExtractor tokenExtractor = new BearerTokenExtractor();
//
//	@Override
//	public void configure(HttpSecurity httpSecurity) throws Exception {
//		httpSecurity.addFilterBefore(permitAuthenticationFilter(), OAuth2AuthenticationProcessingFilter.class);
//	}
//
//	private Filter permitAuthenticationFilter() {
//		return new OncePerRequestFilter() {
//			private boolean matchPermitAll(HttpServletRequest request) {
//				for(RequestMatcher matcher : OAuth2ResourceConfig.PERMIT_ALL_MATCHERS) {
//					if(matcher.matches(request)) {
//						return true;
//					}
//				}
//				return false;
//			}
//
//			@Override
//			protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
//					throws ServletException, IOException {
//				if(matchPermitAll(request)) {
//					//提前验证Token有效性，如果无效，则去除Authorization；如果有效，则保持不变
//					Authentication authentication = tokenExtractor.extract(request);
//					request = new HttpServletRequestWrapper(request) {
//						private Set<String> headerNameSet;
//
//						@Override
//						public Enumeration<String> getHeaderNames() {
//							if(headerNameSet == null) {
//								// first time this method is called, cache the wrapped request's header names:
//								headerNameSet = new HashSet<>();
//								Enumeration<String> wrappedHeaderNames = super.getHeaderNames();
//								while(wrappedHeaderNames.hasMoreElements()) {
//									String name = wrappedHeaderNames.nextElement();
//									if(authentication == null && "Authorization".equalsIgnoreCase(name)) {
//										headerNameSet.add(name);
//									}
//								}
//							}
//							return Collections.enumeration(headerNameSet);
//						}
//
//						@Override
//						public Enumeration<String> getHeaders(String name) {
//							if(authentication == null && "Authorization".equalsIgnoreCase(name)) {
//								return Collections.emptyEnumeration();
//							}
//							return super.getHeaders(name);
//						}
//
//						@Override
//						public String getHeader(String name) {
//							if(authentication == null && "Authorization".equalsIgnoreCase(name)) {
//								return null;
//							}
//							return super.getHeader(name);
//						}
//					};
//				}
//				filterChain.doFilter(request, response);
//			}
//		};
//	}
//}
